package com.mll.snake.views;


import com.mll.snake.ResourceTable;
import ohos.agp.components.Component;
import ohos.agp.render.Canvas;
import ohos.agp.render.MaskFilter;
import ohos.agp.render.Paint;
import ohos.agp.render.PixelMapHolder;
import ohos.agp.utils.Color;
import ohos.agp.utils.Point;
import ohos.agp.utils.Rect;
import ohos.agp.utils.RectFloat;
import ohos.app.Context;
import ohos.global.resource.NotExistException;
import ohos.hiviewdfx.HiLog;
import ohos.hiviewdfx.HiLogLabel;
import ohos.media.image.ImageSource;
import ohos.media.image.PixelMap;
import ohos.media.image.common.AlphaType;
import ohos.media.image.common.PixelFormat;
import ohos.media.image.common.Size;
import ohos.multimodalinput.event.MmiPoint;
import ohos.multimodalinput.event.TouchEvent;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Random;


public class SnakeComponent extends Component implements Component.ScrolledListener {
    public static final String TAG = "SnakeView";

    private Paint outerCirclePaint;
    private Paint innerCirclePaint;
    /** 内圆中心x坐标 */
    private double innerCenterX;
    /** 内圆中心y坐标 */
    private double innerCenterY;

    public float getViewCenterX() {
        return viewCenterX;
    }

    public void setViewCenterX(float viewCenterX) {
        this.viewCenterX = viewCenterX;
    }

    public float getViewCenterY() {
        return viewCenterY;
    }

    public void setViewCenterY(float viewCenterY) {
        this.viewCenterY = viewCenterY;
    }

    /** view中心点x坐标 */
    private float viewCenterX;
    /** view中心点y左边 */
    private float viewCenterY;
    /** view宽高大小，设定宽高相等 */
    private int size;
    /** 外圆半径 */
    private int outerCircleRadius;
    /** 内圆半径 */
    private int innerCircleRadius;

    private int mWidth = 2200;  //view的宽
    private int mHeight = 830; //View的高
    private static final int sXOffset = 0;
    private static final int sYOffset = 0; // X坐标和Y坐标的偏移量，可以修改来缩小游戏范围

    private int BOXWIDTH = 100; //食物的边长，蛇体的宽度
    private Random mRandom = new Random(); //用于产生随机数
    private Point mFoodPosition; //食物的位置
    private boolean mIsFoodDone; //食物是否已经被吃掉

    private ArrayList<Point> mSnakeList;  //蛇体可以看做是很多食物组成的
    private Paint mSnakePaint;  //用于画蛇的画笔
    private double mSnakeDirection = 0; //蛇体运动的方向
    private final int UP = 1;
    private final int DOWN = 2;
    private final int LEFT = 3;
    private final int RIGHT = 4;
    private final int RIGHT_UP = 5;
    private final int RIGHT_DOWM = 6;
    private final int LEFT_UP = 7;
    private final int LEFT_DOWN = 8;
    private boolean firstFlag ;


    //获取图片id时使用
    private int whirlCount = 0;
    private boolean isCorp = false;
    private boolean isScale = false;
    private final static int DEF_UNFILL_COLOR = 0xFF808080;
    private final static int DEF_FILL_COLOR = 0xFF1E90FF;
    private static final HiLogLabel LABEL_LOG = new HiLogLabel(3, 0xD001100, "CustomControlBar");


    private Paint mBgPaint;//游戏背景画笔
    private Paint mFoodPaint;//食物画笔
    private Paint paint;
    private int snakeFood; // 记录当前食物的位置，横坐标*100+纵坐标
    private LinkedList<Integer> snakeArray; // 记录蛇的位置信息，每一节的坐标和食物的一致，横坐标*100+纵坐标
    private DrawTask task = new DrawTask() {
        @Override
        public void onDraw(Component component, Canvas canvas) {
            try {
                drawBg(canvas, mBgPaint);  //画背景
//                if(mIsFoodDone){
                drawFood(canvas, mFoodPaint);//画食物
//                }
                drawSnake(canvas, mSnakePaint); //画蛇
                //画摇杆
                canvas.drawCircle(viewCenterX, viewCenterY, outerCircleRadius, outerCirclePaint);
                canvas.drawCircle((float) innerCenterX, (float) innerCenterY, innerCircleRadius, innerCirclePaint);
            } catch (IOException e) {
                e.printStackTrace();
            } catch (NotExistException e) {
                e.printStackTrace();
            }
        }

    };
    /**
     * 处理手势事件
     */
    public void handleEvent(TouchEvent event) {
        MmiPoint point = event.getPointerScreenPosition(0);
        double distance = Math.sqrt(Math.pow(point.getX()-viewCenterX, 2) + Math.pow(point.getY()-viewCenterY, 2)); //触摸点与view中心距离
        int n = outerCircleRadius-innerCircleRadius;
        System.out.println("++++++++++++_______________________+++++++++++++++" + distance + "+++++++++" + n);
        if (distance < outerCircleRadius-innerCircleRadius) {
            //在自由域之内，触摸点实时作为内圆圆心
            innerCenterX = point.getX();
            innerCenterY = point.getY();
            invalidate();
        } else {
            //在自由域之外，内圆圆心在触摸点与外圆圆心的线段上
            updateInnerCircelCenter(event);
        }
    }

    /**
     * 在自由域外更新内圆中心坐标
     */
    public void updateInnerCircelCenter(TouchEvent event) {
        MmiPoint point = event.getPointerScreenPosition(0);
        double distance = Math.sqrt(Math.pow(point.getX()-viewCenterX, 2) + Math.pow(point.getY()-viewCenterY, 2));  //当前触摸点到圆心的距离
        int innerDistance = outerCircleRadius-innerCircleRadius;  //内圆圆心到中心点距离
        //相似三角形的性质，两个相似三角形各边比例相等得到等式
        innerCenterX = (point.getX()-viewCenterX)*innerDistance/distance + viewCenterX;
        innerCenterY = (point.getY()-viewCenterY)*innerDistance/distance + viewCenterY;

        invalidate();
    }

    /**
     * 恢复内圆到view中心位置
     */
    public void restorePosition() {
        innerCenterX = viewCenterX;
        innerCenterY = viewCenterY;
        invalidate();
    }
    private void init() {
        size = 200;

        innerCenterX = 2000;
        innerCenterY = 650;
        viewCenterX = 2000;
        viewCenterY = 650;
        outerCircleRadius = size/2;
        innerCircleRadius = size/5;
        outerCirclePaint = new Paint();
        outerCirclePaint.setColor(Color.GREEN);
        outerCirclePaint.setAlpha(0.6f);
        outerCirclePaint.setAntiAlias(true);
        outerCirclePaint.setMaskFilter(new MaskFilter(50, MaskFilter.Blur.INNER));

        innerCirclePaint = new Paint();
        innerCirclePaint.setAlpha(0.7f);
        innerCirclePaint.setColor(Color.RED);
        innerCirclePaint.setAntiAlias(true);
    }

    public SnakeComponent(Context context) {
        super(context);
        init();
        mSnakeList = new ArrayList<Point>();
        Point point = new Point();
        mSnakeList.add(point);
        mSnakePaint = new Paint();
        //蛇的颜色
        mSnakePaint.setColor(Color.GREEN);
        mSnakePaint.setStyle(Paint.Style.FILLANDSTROKE_STYLE);
        //蛇初始位置
        mSnakeList.add(new Point(200, 150));
        firstFlag = true;

        mIsFoodDone = true;
        mFoodPosition = new Point();

        //食物的颜色
        mFoodPaint = new Paint();
        mFoodPaint.setColor(Color.CYAN);
        mFoodPaint.setStyle(Paint.Style.FILL_STYLE);

        mBgPaint = new Paint();
        mBgPaint.setColor(Color.YELLOW);
        mBgPaint.setStyle(Paint.Style.FILL_STYLE);
        Paint paint = new Paint();
        paint.setColor(Color.WHITE);   //初始化各种画笔
        addDrawTask(task);
    }

    @Override
    public void addDrawTask(DrawTask task) {
        super.addDrawTask(task);
        task.onDraw(this, mCanvasForTaskOverContent);
    }

    //画背景 这里通过sXOffset, sYOffset可以实现对蛇活动区域的限制
    private void drawBg(Canvas canvas, Paint paint) {
//        //设置背景颜色
//        paint.setColor(Color.BLUE);
//        RectFloat rect = new RectFloat(sXOffset, sYOffset, mWidth - sXOffset, mHeight - sYOffset);
//        canvas.drawRect(rect, paint);
        ImageSource.SourceOptions sourceOptions = null;
        ImageSource imageSource = null;
        ImageSource.DecodingOptions decodingOptions = null;
        PixelMap pixelMap = null;
        PixelMapHolder pixelMapHolder = null;
        //获取图片输入流
        InputStream inputStream  = null;//向上的蛇头
        try {
            inputStream = getContext().getResourceManager().getResource(ResourceTable.Media_game_bak);
            sourceOptions = new ImageSource.SourceOptions();

            //设置格式
            sourceOptions.formatHint = "image/png";
            //获取图片资源
            imageSource = ImageSource.create(inputStream, sourceOptions);
            //创建DecodingOptions对象用来创建PixeMap对象
            decodingOptions = new ImageSource.DecodingOptions();
            //获取PixeMap对象
//            pixelMap = imageSource.createPixelmap(decodingOptions);
            pixelMap = getPixelMapFromResource(ResourceTable.Media_game_bak);
            //获取PixelMapHolder对象
            pixelMapHolder = new PixelMapHolder(pixelMap);
            canvas.drawPixelMapHolder(pixelMapHolder,0,0,paint);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (NotExistException e) {
            e.printStackTrace();
        }

    }

    /**
     * 画蛇
     *
     * @param canvas
     * @param paint
     * @throws IOException
     * @throws NotExistException
     */
    private void drawSnake(Canvas canvas, Paint paint) throws IOException, NotExistException {
        RectFloat rect = null;
        Point point0 = mSnakeList.get(0);
        InputStream inputStream = null;
        ImageSource.SourceOptions sourceOptions = null;
        ImageSource imageSource = null;
        ImageSource.DecodingOptions decodingOptions = null;
        PixelMap pixelMap = null;
        PixelMapHolder pixelMapHolder = null;
        //画蛇头
        rect = new RectFloat(point0.getPointX(), point0.getPointY(), point0.getPointX() + BOXWIDTH, point0.getPointY() + BOXWIDTH);
        //获取图片输入流
        inputStream = getContext().getResourceManager().getResource(ResourceTable.Media_tigger2);//向上的蛇头
        sourceOptions = new ImageSource.SourceOptions();
        //设置格式
        sourceOptions.formatHint = "image/png";
        //获取图片资源
        imageSource = ImageSource.create(inputStream, sourceOptions);
        //创建DecodingOptions对象用来创建PixeMap对象
        decodingOptions = new ImageSource.DecodingOptions();
        //获取PixeMap对象
//                pixelMap = imageSource.createPixelmap(decodingOptions);
        pixelMap = getPixelMapFromResource(ResourceTable.Media_tigger2);
        //获取PixelMapHolder对象
        pixelMapHolder = new PixelMapHolder(pixelMap);
        //把蛇头画在画布上
        canvas.drawPixelMapHolderRect(pixelMapHolder, rect, paint);
        //蛇移动，更新list为下一次刷新做准备
        snakeMove(mSnakeList, mSnakeDirection);
        if (isFoodEaten()) {  //如果吃了食物，长度加1
            mIsFoodDone = true;
        } else {    //如果没有吃食物，由于前进时加了一个 这里删除尾巴，出现移动的效果
            mSnakeList.remove(mSnakeList.size() - 1);
        }
    }

    public void snakeMove(ArrayList<Point> list, double direction) {
        //Log.e(TAG," snakeMove ArrayList = " + list.toString());
        Point orighead = list.get(0);
        Point newhead = new Point();
        if(direction <= 90.0){
            newhead.position[0] = (float) (orighead.getPointXToInt() + BOXWIDTH * Math.cos(direction));//x坐标
            newhead.position[1] = (float) (orighead.getPointYToInt() + BOXWIDTH * Math.sin(direction));//y坐标
        }else if(direction <= 180.0 && direction > 90.0){
            newhead.position[0] = (float) (orighead.getPointXToInt() - BOXWIDTH * Math.cos(180.0 - direction));//x坐标
            newhead.position[1] = (float) (orighead.getPointYToInt() + BOXWIDTH * Math.sin(180.0 - direction));//y坐标
        }
        else if(direction > 180.0 && direction <= 270.0){
            newhead.position[0] = (float) (orighead.getPointXToInt() - BOXWIDTH * Math.cos(direction - 180.0));//x坐标
            newhead.position[1] = (float) (orighead.getPointYToInt() - BOXWIDTH * Math.sin(direction - 180.0));//y坐标
        }else if(direction < 270.0 && direction <= 360.0){
            newhead.position[0] = (float) (orighead.getPointXToInt() + BOXWIDTH * Math.cos(360.0 - direction));//x坐标
            newhead.position[1] = (float) (orighead.getPointYToInt() - BOXWIDTH * Math.sin(360.0 - direction));//y坐标
        }
        adjustHead(newhead);
        list.add(0, newhead);
    }

    /**
     * 画食物
     *
     * @param canvas
     * @param paint
     * @throws IOException
     * @throws NotExistException
     */
    private void drawFood(Canvas canvas, Paint paint) throws IOException, NotExistException {
        RectFloat food =null;
        PixelMapHolder pixelMapHolder = null;
        int i = 2;
        if (mIsFoodDone) {  //只在前一个食物被吃掉的情况下才产生食物
            int x = mRandom.nextInt(mWidth - 2 * sXOffset - BOXWIDTH) + sXOffset;
            int y = mRandom.nextInt(mHeight - 2 * sYOffset - BOXWIDTH) + sYOffset;
            mFoodPosition = new Point(new Float(x), new Float(y));
            mIsFoodDone = false;
            if ((mSnakeList.size() - 2) % 5 == 0) {
                BOXWIDTH += 7;
            }
            Random r = new Random();
            i = r.nextInt(3);
        }
        //获取图片输入流
        int[] array = new int[5];
        array[0] = ResourceTable.Media_food1;
        array[1] = ResourceTable.Media_food2;
        array[2] = ResourceTable.Media_food3;

        InputStream inputStream = getContext().getResourceManager().getResource(array[2]);
        ImageSource.SourceOptions sourceOptions = new ImageSource.SourceOptions();
        //设置格式
        sourceOptions.formatHint = "image/png";
        //获取图片资源
        ImageSource imageSource = ImageSource.create(inputStream, sourceOptions);
        //创建DecodingOptions对象用来创建PixeMap对象
        ImageSource.DecodingOptions decodingOptions = new ImageSource.DecodingOptions();
        //获取PixeMap对象
        PixelMap pixelMap = getPixelMapFromResource(ResourceTable.Media_food3);
        //获取PixelMapHolder对象
        pixelMapHolder = new PixelMapHolder(pixelMap);
        food = new RectFloat(mFoodPosition.getPointXToInt(), mFoodPosition.getPointYToInt(), mFoodPosition.getPointXToInt() + BOXWIDTH / 10, mFoodPosition.getPointYToInt() + BOXWIDTH / 10);
        //把食物画在画布上
        canvas.drawPixelMapHolderRect(pixelMapHolder, food, paint);
    }

    //边界判断
    private boolean isOutBound(Point point) {
        if (point.getPointXToInt() < sXOffset || point.getPointXToInt() > mWidth - sXOffset) return true;
        if (point.getPointYToInt() < sYOffset || point.getPointYToInt() > mHeight - sYOffset) return true;
        return false;
    }

    //出了边界，重新回来
    private void adjustHead(Point point) {
        //超出左边界
        if (point.getPointXToInt() < sXOffset) {
            point.position[0] = mWidth + sYOffset - BOXWIDTH;
            point.position[1] = point.position[1];
        }
        //超出右边界
        if (point.getPointXToInt() > mWidth - sXOffset) {
            point.position[0] = sXOffset + BOXWIDTH;
            point.position[1] = point.position[1];
        }
        //超出上边界
        if (point.getPointYToInt() < sYOffset) {
            point.position[0] = point.position[0];
            point.position[1] = mHeight - BOXWIDTH;
        }
        //超出下边界
        if (point.getPointYToInt() > mHeight - sYOffset) {
            point.position[0] = point.position[0];
            point.position[1] = BOXWIDTH;
        }
    }

    //判断食物是否可以被吃
    private boolean isFoodEaten() {
        if (!mIsFoodDone) {
            Rect foodrect = new Rect(mFoodPosition.getPointXToInt(), mFoodPosition.getPointYToInt(), mFoodPosition.getPointXToInt() + BOXWIDTH, mFoodPosition.getPointYToInt() + BOXWIDTH);
            Point head = mSnakeList.get(0);
            Rect headrect = new Rect(head.getPointXToInt(), head.getPointYToInt(), head.getPointXToInt() + BOXWIDTH, head.getPointYToInt() + BOXWIDTH);
            return foodrect.getIntersectRect(headrect);
        }
        return false;
    }

    @Override
    public void onContentScrolled(Component component, int i, int i1, int i2, int i3) {
        mWidth = i;
        mHeight = i1;
    }

    /**
     * 设置蛇的运动方向
     *
     * @param mSnakeDirection
     */
    public void setmSnakeDirection(double mSnakeDirection) {
        this.mSnakeDirection = mSnakeDirection;
    }

    public double getmSnakeDirection() {
        return mSnakeDirection;
    }

    public ArrayList<Point> getmSnakeList() {
        return mSnakeList;
    }

    /**
     * 通过图片ID返回PixelMap
     *
     * @param resourceId 图片的资源ID
     * @return 图片的PixelMap
     */
    private PixelMap getPixelMapFromResource(int resourceId) {
        InputStream inputStream = null;
        try {
            // 创建图像数据源ImageSource对象
            inputStream = getContext().getResourceManager().getResource(resourceId);
            ImageSource.SourceOptions srcOpts = new ImageSource.SourceOptions();
            srcOpts.formatHint = "image/jpg";
            ImageSource imageSource = ImageSource.create(inputStream, srcOpts);

            // 设置图片参数
            ImageSource.DecodingOptions decodingOptions = new ImageSource.DecodingOptions();
            // 旋转
            decodingOptions.rotateDegrees = 90 * whirlCount;
            // 缩放
            decodingOptions.desiredSize = new Size(isScale ? 512 : 0, isScale ? 384 : 0);
            // 剪裁
            decodingOptions.desiredRegion = new ohos.media.image.common.Rect(0, 0, isCorp ? 1024 : 0, isCorp ? 400 : 0);
            decodingOptions.desiredPixelFormat = PixelFormat.ARGB_8888;
            return imageSource.createPixelmap(decodingOptions);
        } catch (IOException e) {
            HiLog.info(LABEL_LOG, "IOException");
        } catch (NotExistException e) {
            HiLog.info(LABEL_LOG, "NotExistException");
        } finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    HiLog.info(LABEL_LOG, "inputStream IOException");
                }
            }
        }
        return null;
    }

}
